/**
 * Project Name:nplus1
 * File Name:BaseRestController.java
 * Package Name:com.gamma.nplus1.common.web
 * Date:2017年5月18日下午1:57:01
 * Copyright (c) 2017, nplus1 Co., Ltd. All Rights Reserved.
 *
*/

package com.gamma.nplus1.common.web;


import java.util.List;

import javax.validation.ConstraintViolationException;
import javax.validation.ValidationException;
import javax.validation.Validator;

import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.http.converter.HttpMessageNotReadableException;
import org.springframework.web.HttpMediaTypeNotSupportedException;
import org.springframework.web.HttpRequestMethodNotSupportedException;
import org.springframework.web.bind.annotation.ExceptionHandler;

import com.gamma.nplus1.common.beanvalidator.BeanValidators;
import com.gamma.nplus1.common.entity.RestApiResult;
import com.gamma.nplus1.common.exception.InvalidSignedException;


/**
 * ClassName:BaseRestController <br/>
 * Function: rest api控制器支持类. <br/>
 * Date:     2017年5月18日 下午1:57:01 <br/>
 * @author   jeno
 * @version  
 * @since    JDK 1.7
 */
public abstract class BaseRestController {
	
	/**
	 * 验证Bean实例对象
	 */
	@Autowired
	protected Validator validator;
	
	/**
	 * 日志对象
	 */
	protected Logger logger = LoggerFactory.getLogger(getClass());

	/**
	 * 
	 * handleValidationException:(416). <br/>
	 *
	 * @author jeno
	 * @param e
	 * @return
	 * @since JDK 1.7
	 */
	@ExceptionHandler({ValidationException.class})
	public ResponseEntity<RestApiResult> handleValidationException(ValidationException e) {
        logger.error("Requested Range not satisfiable", e);
        return this.buildExceptionResult(416, e.getMessage());
    }

	/**
	 * 
	 * handleHttpMessageNotReadableException:(400 - Bad Request). <br/>
	 *
	 * @author jeno
	 * @param e
	 * @return
	 * @since JDK 1.7
	 */
	@ExceptionHandler({HttpMessageNotReadableException.class})
	public ResponseEntity<RestApiResult> handleHttpMessageNotReadableException(HttpMessageNotReadableException e) {
		logger.error("参数解析失败", e);
		return this.buildExceptionResult(400, e.getMessage());
	}
	
	/**
	 * 
	 * handleHttpRequestMethodNotSupportedException:(405 - Method Not Allowed). <br/>
	 *
	 * @author jeno
	 * @param e
	 * @return
	 * @since JDK 1.7
	 */
	@ExceptionHandler({HttpRequestMethodNotSupportedException.class})
	public ResponseEntity<RestApiResult> handleHttpRequestMethodNotSupportedException(HttpRequestMethodNotSupportedException e) {
		logger.error("不支持当前请求方法", e);
		return this.buildExceptionResult(405, e.getMessage());
	}
	
	/**
	 * 
	 * handleHttpMediaTypeNotSupportedException:(415 - Unsupported Media Type). <br/>
	 *
	 * @author jeno
	 * @param e
	 * @return
	 * @since JDK 1.7
	 */
	@ExceptionHandler({HttpMediaTypeNotSupportedException.class})
	public ResponseEntity<RestApiResult> handleHttpMediaTypeNotSupportedException(HttpMediaTypeNotSupportedException e) {
		logger.error("media type not support", e);
		return this.buildExceptionResult(415, e.getMessage());
	}
	
	/**
	 * 
	 * handleException:(500 - Internal Server Error). <br/>
	 *
	 * @author jeno
	 * @param e
	 * @return
	 * @since JDK 1.7
	 */
	@ExceptionHandler({Exception.class})
	public ResponseEntity<RestApiResult> handleException(Exception e) {
		logger.error("internal server error", e);
		return this.buildExceptionResult(500, "internal server error");
	}
	
	/**
	 * 
	 * handleException:(403 - restapi invalid sign). <br/>
	 *
	 * @author jeno
	 * @param e
	 * @return
	 * @since JDK 1.7
	 */
	@ExceptionHandler({InvalidSignedException.class})
	public ResponseEntity<RestApiResult> handleInvalidSignedException(InvalidSignedException e) {
		logger.error("无效签名", e);
		return this.buildExceptionResult(403, e.getMessage());
	}
	
	/**
	 * 
	 * beanValidator:(服务端参数有效性验证). <br/>
	 *
	 * @author jeno
	 * @param object 验证的实体对象
	 * @param groups 验证组
	 * @return 将错误信息添加到 返回值中
	 * @since JDK 1.7
	 */
	protected String beanValidator(Object object, Class<?>... groups) {
		try{
			BeanValidators.validateWithException(validator, object, groups);
		}catch(ConstraintViolationException ex){
			List<String> list = BeanValidators.extractPropertyAndMessageAsList(ex, ": ");
			list.add(0, "数据验证失败：");
			String[] messages = list.toArray(new String[]{});
			
			StringBuilder sb = new StringBuilder();
			for (String message : messages){
				sb.append(message).append(messages.length>1?",":"");
			}
			
			return sb.toString();
		}
		
		return StringUtils.EMPTY;
	}
	
	/**
	 * 
	 * buildExceptionResult:(组织一个错误返回响应). <br/>
	 *
	 * @author jeno
	 * @param httpcode
	 * @param message
	 * @return
	 * @since JDK 1.7
	 */
	protected ResponseEntity<RestApiResult> buildExceptionResult(int httpcode,String msg) {
		RestApiResult faltResult = new RestApiResult(httpcode, msg);
		return new ResponseEntity<RestApiResult>(faltResult, HttpStatus.OK);
	}
	
	/**
	 * 
	 * buildSuccessResult:(组织一个成功的返回响应). <br/>
	 *
	 * @author jeno
	 * @param data
	 * @return
	 * @since JDK 1.7
	 */
	protected ResponseEntity<Object> buildSuccessResult(Object data , String msg) {
		RestApiResult successResult = new RestApiResult(200, msg,data);
		return new ResponseEntity<Object>(successResult, HttpStatus.OK);
	}
	
	/**
	 * 
	 * buildOrderByStr:(组织排序字符串). <br/>
	 *
	 * @author jeno
	 * @param sortby
	 * @param order
	 * @return
	 * @since JDK 1.7
	 */
	protected String buildOrderByStr(String sortby,String order) {
		StringBuilder sb = new StringBuilder();
		
		if (StringUtils.isBlank(sortby)) {
			return sb.toString();
		} else {
			sb.append(sortby);
		}
		
		if (StringUtils.isBlank(order)) {
			sb.append(" ASC");
		} else {
			sb.append(order);
		}
		
		return sb.toString();
	}
}

